package com.wlf.admin.common.quartz;

import com.wlf.admin.system.domain.ScheduleJob;
import lombok.NoArgsConstructor;
import org.quartz.*;

/**
 * Quartz 服务
 * <p>
 * @serial 2.0.0
 * @author 就眠儀式
 */
@NoArgsConstructor
public class QuartzService {

    /**
     * 定时任务标识 Key
     */
    private static final String SCHEDULE_NAME = "qrtz_";

    /**
     * 触发器 KEY
     */
    public static TriggerKey getTriggerKey(Long jobId) {
        return TriggerKey.triggerKey(SCHEDULE_NAME + jobId);
    }

    /**
     * 定时器 Key
     */
    public static JobKey getJobKey(Long jobId) {
        return JobKey.jobKey(SCHEDULE_NAME + jobId);
    }

    /**
     * 表达式触发器
     */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            return null;
        }
    }

    public static SimpleTrigger getSimpleTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (SimpleTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            return null;
        }
    }

    public static Trigger getTrigger(Scheduler scheduler, Long jobId) {
        try {
            return scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            return null;
        }
    }

    /**
     * Describe: 创建定时任务
     * Param: Scheduler ScheduleJobBean
     * Return: null
     */
    public static void createJob(Scheduler scheduler, ScheduleJob scheduleJob) {
        try {
            // 构建定时器
            JobDetail jobDetail = JobBuilder.newJob(QuartzExecute.class).withIdentity(getJobKey(scheduleJob.getId())).build();

            Trigger trigger = null;

            if (scheduleJob.getJobType().equals(0)) {
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                        .cronSchedule(scheduleJob.getCronExpression())
                        .withMisfireHandlingInstructionDoNothing();

                trigger = TriggerBuilder.newTrigger()
                        .withIdentity(getTriggerKey(scheduleJob.getId()))
                        .withSchedule(scheduleBuilder)
                        .build();
            }
            if (scheduleJob.getJobType().equals(1)) {
                SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder
                        .simpleSchedule()
                        .repeatForever();
                switch (scheduleJob.getIntervalUnit()) {
                    case 0 -> simpleScheduleBuilder.withIntervalInMilliseconds(scheduleJob.getInterval());
                    case 1 -> simpleScheduleBuilder.withIntervalInSeconds(scheduleJob.getInterval());
                    case 2 -> simpleScheduleBuilder.withIntervalInMinutes(scheduleJob.getInterval());
                    case 3 -> simpleScheduleBuilder.withIntervalInHours(scheduleJob.getInterval());
                }
                trigger = TriggerBuilder.newTrigger()
                        .withIdentity(getTriggerKey(scheduleJob.getId()))
                        .withSchedule(simpleScheduleBuilder)
                        .build();
            }
            jobDetail.getJobDataMap().put(ScheduleJob.JOB_PARAM_KEY, scheduleJob);
            assert trigger != null;
            scheduler.scheduleJob(jobDetail, trigger);
            // 如果该定时器处于暂停状态
            if (1 == scheduleJob.getStatus()) {
                pauseJob(scheduler, scheduleJob.getId());
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("createJob Fail", e);
        }
    }

    /**
     * Describe: 更新定时任务
     * Param: Scheduler ScheduleJobBean
     * Return: null
     */
    public static void updateJob(Scheduler scheduler, ScheduleJob scheduleJob) {
        try {
            TriggerKey triggerKey = getTriggerKey(scheduleJob.getId());
            Trigger trigger = getTrigger(scheduler, scheduleJob.getId());
            assert trigger != null;
            if (scheduleJob.getJobType().equals(0)) {
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                        .cronSchedule(scheduleJob.getCronExpression())
                        .withMisfireHandlingInstructionDoNothing();
                trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            }
            if (scheduleJob.getJobType().equals(1)) {
                SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder
                        .simpleSchedule()
                        .repeatForever();
                switch (scheduleJob.getIntervalUnit()) {
                    case 0 -> simpleScheduleBuilder.withIntervalInMilliseconds(scheduleJob.getInterval());
                    case 1 -> simpleScheduleBuilder.withIntervalInSeconds(scheduleJob.getInterval());
                    case 2 -> simpleScheduleBuilder.withIntervalInMinutes(scheduleJob.getInterval());
                    case 3 -> simpleScheduleBuilder.withIntervalInHours(scheduleJob.getInterval());
                }

                trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(simpleScheduleBuilder).build();
            }
            trigger.getJobDataMap().put(ScheduleJob.JOB_PARAM_KEY, scheduleJob);
            scheduler.rescheduleJob(triggerKey, trigger);
            if (1 == scheduleJob.getStatus()) {
                pauseJob(scheduler, scheduleJob.getId());
            }
        } catch (SchedulerException e) {
            throw new RuntimeException("updateJob Fail", e);
        }
    }

    /**
     * Describe: 停止定时任务
     * Param: Scheduler ScheduleJobBean
     * Return: null
     */
    public static void pauseJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("pauseJob Fail", e);
        }
    }

    /**
     * Describe: 恢复定时任务
     * Param: Scheduler ScheduleJobBean
     * Return: null
     */
    public static void resumeJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("resumeJob Fail", e);
        }
    }

    /**
     * Describe: 删除定时任务
     * Param: Scheduler ScheduleJobBean
     * Return: null
     */
    public static void deleteJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            throw new RuntimeException("deleteJob Fail", e);
        }
    }

    /**
     * Describe: 执行定时任务
     * Param: Scheduler ScheduleJobBean
     * Return: null
     */
    public static void run(Scheduler scheduler, ScheduleJob scheduleJob) {
        try {
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(ScheduleJob.JOB_PARAM_KEY, scheduleJob);
            scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap);
        } catch (SchedulerException e) {
            throw new RuntimeException("init Fail", e);
        }
    }

}
